AppTitle "Celestial Rift - Version 1.1 (C)2001 Myke P" ;what this program will be called in MICROSOFT WINDOWS.
;This makes two CONSTants. These are values which will NOT change at any point in the program, so we set their values now.
Const SCREEN_WIDTH = 800
Const SCREEN_HEIGHT = 600
;This is the code which tells Blitz what Display Resolution to use on the Graphics Card. The "GRAPHICS" command should always be placed before you do
;*anything* image-related in your program
Graphics SCREEN_WIDTH,SCREEN_HEIGHT,0,1 ;start the graphics mode at SCREEN_WIDTH by SCREEN_HEIGHT, let Blitz choose the depth (,0) and run full screen (,1)
;more program CONSTants..
Const GAME_AREA_X = 50000 ;these two set the size of the map. You *should* keep them the same, 'cos the radar is square
Const GAME_AREA_Y = 50000 ;but technically, you can change the values to anything you like! ;)
;the following constants are keyboard "SCAN" codes. Every key on the keyboard has a number. You can get the full list in your Blitz manual.
Const KEY_CLOCKWISE = 25 ;(p)
Const KEY_ANTICWISE = 24 ;(o)
Const KEY_SPEEDUP = 16 ;(q)
Const KEY_SPEEDDOWN = 30 ;(a)
Const KEY_FIRE = 57 ;(Space)
Const KEY_HYPER = 2 ;(1)
Const KEY_BOOST = 50 ;(m)
Const KEY_CLOAK = 46 ;(c)
Const KEY_QUIT = 1 ;(Escape)
Const KEY_PAUSE = 7 ;(Number 6 on the main keyboard)
Const KEY_DEBUG = 59 ;(F1)
Const KEY_SAVESCREEN = 88 ;(F12)
;the following constants affect the way the game plays. Feel free to mess with the values..
Const INCR_ROTATE# = 5 ;.. but DON'T touch this, otherwise the game will crash (I only drew the animation frames for 5 degree intervals!)
Const INCR_SPEED# = 0.5
Const INCR_SLOW# = 0.125
Const INCR_BOOSTERS_UP# = 0.025
Const INCR_BOOSTERS_DOWN# = .75
Const INCR_CLOAK_UP#= 0.0125
Const INCR_CLOAK_DOWN# = .25
Const SPEED_MAX = 25
Const SPEED_MIN = -5
;set up changable variables for game/menu (with initial values, if you like - i.e.: you could just as soon as set them later!)
Global FLAG_GAMEON = 1
Global FLAG_PAUSE
Global FLAG_SAVESCREEN = 0
Global FLAG_DEBUG = 0
Global FLAG_GAMESTARTER
Global PLAYER_SHIELD#
Global PLAYER_BOOSTERS#
Global PLAYER_CLOAK#
Global PLAYER_JUMPS
Global PLAYER_SPEED#
Global PLAYER_ANGLE#
Global PLAYER_X#
Global PLAYER_Y#
Global PLAYER_SCORE
Global HI_SCORE
Global timer
Global frames
Global starson
Global game_pause_frame
Global game_accept_pause
Global game_pause_stat
Global hypercount# ;a "#" symbol after the variable name means it can hold a FLOATING POINT number, i.e.: 190.1234
Global pausecount ;without the "#" symbol, the variable is, by default, an INTEGER (Whole) number, i.e.: 190
Global cloakon# ;use the symbols when you are *sure* that you want it to hold specific types of data:
Global frame1 ;# - floating point
Global frame2 ;% - integer (whole number)
Global frame3 ;$ - string (text, i.e.: "MYKE 12345"
Global frame4 ;
Global frame5
Global frame6
Global frame7
Global frame8
Global tempstr$
timer = CreateTimer(50) ;create a timer set at 50ms (game speed) - play with this to see how you can increase or decrease the speed of the game.
;this should be set at a speed which will look near enough the same on *every* PC it will be played on.
;My PC (a 733MHz PIII with an nVidia GeForce card) will handle upwards of 150 frames per second, quite happily
;but 'lesser' machines will not. 50, therefore, is quite sensible For a game of this nature, who's minimum system spec
;will be something like a PII 300MHz machine (i.e.: Blitz Basic's minimum spec!)
;NOTE: there's no need to organise your variable declarations, as I have here, into sections. They can appear in any order you like, before the main program begins.
;I just do this, 'cos it looks right professional! :))))
;picture/animation (and related) variables
Dim game_stars(5) ;these 3 are ARRAYS. An array is automatically Global, but requires the Keyword (Yellow bit) DIM instead. This means "Dimension".
Dim game_icons(4) ;the arrays have single dimensions (imagine one straight line of boxes, each that can contain a single variable) 0 to.. (the number in brackets)
Global game_icon_dot
Global game_player
Global game_player_frame
Global game_player_dot
Global game_bullet_player
Global game_gameover
Global game_paused
;Types are like Structures in C. You have a "Type" called whatever. Then you can make multiple versions of the type. Each version of the Type has the same properties, i.e.:
;a FISH (the Type) has EYES, MOUTH, SCALES And FINS (it's properties) - ALL FISH have these properties.
;a DOG (the Type) has EYES, MOUTH, FUR and TAIL (it's properties) - ALL DOGS have these properties (look like this.)
Type stars ;create "Type" for parallex stars
Field depth,x#,y# ;each star has a depth, x and y position
End Type
Type icons ;same for icons
Field x#,y#,style,frame#
End Type
;this code makes 4 'objects' in a "Type" called "ICONS".
For i = 1 To 4 ;do this 1, 2, 3, 4 times
icon.icons = New icons ;create a new icon
icon\style = i ;the icon style for each new icon is equal to the increment of i (i.e.: 1, 2, 3 or 4!)
icon\frame = Int(Rnd(0,5)) ;create a random frame number between 0 and 5 for each new icon
Next
menustars = SCREEN_HEIGHT/3 ;generate a number of stars, so that they look dense enough on all test resolutions
starson = 1 ;tells the program to show the stars (see later)
For i=0 To menustars ;create <menustars> number of stars in the STARS type
star.stars=New stars ;add a new star for each increment of i
Next
;this code loads the image numbers into an array called "game_ stars", which we DIMmed earlier. It has 6 containers (0,1,2,3,4,5) but I'm only using 1 to 5!
;an "image number" is what Blitz uses to reference graphics held in the Video Memory, i.e.:
;1. Image number 12 is a picture of a flower.
;2. Make a variable called "flower_pic" = 12
;3. Wherever Blitz is told to draw "flower_pic", reference image number 12 in the Video Memory.
game_stars(1) = LoadImage("GfxRes/backg-star-1.bmp") ;container (1) in "game_stars" holds the image number for this picture ("GfxRes/backg-star-1.bmp")
MaskImage game_stars(i),255,0,255 ;mask the images for each star, so that MAGENTA (255,0,255) is the transparent colour
Next
;similarly, this code loads the image numbers into an array called "game_icons"
;however, these are images that contain the frames of an Animation, so a different Load command is used.
game_icons(1) = LoadAnimImage("GfxRes/icon-boost.bmp",32,32,0,6) ;LoadAnimImage has the same structure as LoadImage, with additional numbers after the picture filename
game_icons(3) = LoadAnimImage("GfxRes/icon-cloak.bmp",32,32,0,6) ;and the Number of Frames in the Image (as *you* would count them (in this case 6)
game_icons(4) = LoadAnimImage("GfxRes/icon-jump.bmp",32,32,0,6) ;have a look at the file "icon-boost" in Paint Shop Pro and see for yourself the 6 frames of animation.
For i = 1 To 4
MaskImage game_icons(i),255,0,255 ;mask the images for each icon, so that MAGENTA (255,0,255) is the transparent colour
Next
;notice in the following code, we're loading (and MASKING) graphics in exactly the same way as before, but into regular variables instead of arrays.
;this next bit is all animations
game_player = LoadAnimImage("GfxRes/player-ship.bmp",80,80,0,72) ;load in the 'sprite' for the player ship
MaskImage game_player,255,0,255 ;mask the images for the player ship, so that MAGENTA (255,0,255) is the transparent colour
;these are all plain single-frame pictures
;game piccies
game_gameover = LoadImage("GfxRes/game-gameover.bmp") ;the game over logo, which I tend to see a lot of.. :(
game_paused = LoadImage("GfxRes/game-paused.bmp") ;the paused logo
game_player_dot = LoadImage("GfxRes/player-radardot.bmp") ;radar dots for the player and bonus icons respectively
If PLAYER_X < 0 Then ;if the PLAYER_X value is less than 0, then wrap your position around the map
PLAYER_X = (PLAYER_X + GAME_AREA_X) ;by adding the GAME_AREA_X value to the negative value, i.e.: -5 becomes 19995 on a 20000 X pixel map.
End If
If PLAYER_X > GAME_AREA_X Then ;the same in reverse, i.e. 20004 becomes 4 on the same map.
PLAYER_X = (PLAYER_X - GAME_AREA_X)
End If
If PLAYER_Y < 0 Then ;and now the same for the Y direction
PLAYER_Y = (PLAYER_Y + GAME_AREA_Y)
End If
If PLAYER_Y > GAME_AREA_Y Then
PLAYER_Y = (PLAYER_Y - GAME_AREA_Y)
End If
For icon.icons=Each icons ;the "icons" don't move from their randomly set x,y position, so all we need to do for them is
icon\frame = icon\frame+.5 ;update their animation frame number. There are 6 frames, and we're incrementing at 0.5 frames per update.
If Int(icon\frame) = 6 Then ;in real terms, this means we'll be updating the frame number every 2 updates.
icon\frame = 0 ;Because the icon animations are simple 0 to 5 cycling animations, when the frame number reaches 6, we flip it back to 0
End If ;to start the sequence again.
Next
;this next bit of code creates the "simple but effective" Hyperjump event, based entirely on the value of "hypercount" being set to 1, earlier in the code.
If hypercount > 0 Then
If (hypercount/2 = Int(hypercount/2)) Then ;this line says "If the value of 'hypercount' is an EVEN number"
;because 5 (an odd number) would be 2.5 when devided by 2, but conversion to an INTeger gives 3.
;2.5 does NOT equal 3!
;all of this simply rotates the HyperJump ships in different offset directions
;the only difference is, we're not bothering with degrees here, just animation frame numbers, i.e.: 355 degrees is frame 71 (i.e.: 355/5 degree increment)
frame1 = frame1 + 3
frame2 = frame2 - 3
frame3 = frame1 + 9
frame4 = frame2 - 9
frame5 = frame1 + 36
frame6 = frame2 - 36
frame7 = frame1 + 54
frame8 = frame2 - 54
If frame1 >=72 Then
frame1 = frame1-72
End If
If frame1 < 0 Then
frame1 = frame1+72
End If
If frame2 >=72 Then
frame2 = frame2-72
End If
If frame2 < 0 Then
frame2 = frame2+72
End If
If frame3 >=72 Then
frame3 = frame3-72
End If
If frame3 < 0 Then
frame3 = frame3+72
End If
If frame4 >=72 Then
frame4 = frame4-72
End If
If frame4 < 0 Then
frame4 = frame4+72
End If
If frame5 >=72 Then
frame5 = frame5-72
End If
If frame5 < 0 Then
frame5 = frame5+72
End If
If frame6 >=72 Then
frame6 = frame6-72
End If
If frame6 < 0 Then
frame6 = frame6+72
End If
If frame7 >=72 Then
frame7 = frame7-72
End If
If frame7 < 0 Then
frame7 = frame7+72
End If
If frame8 >=72 Then
frame8 = frame8-72
End If
If frame8 < 0 Then
frame8 = frame8+72
End If
End If ;end of the "if hypercount is EVEN" IF statement
;this bit increases the value of "hypercount" until it reaches 200
hypercount = hypercount + 1
If hypercount > 0 And hypercount <= 102 Then ;between 0 and 102, the player speed increases
PLAYER_SPEED = PLAYER_SPEED + 2
ElseIf hypercount > 102 And hypercount < 200 Then ;between 102 and 200, the player speed decreases (but only if FLAG_GAMESTARTER is 0)
If FLAG_GAMESTARTER = 0 Then ;this is because when the game starts, the player speed is 0, but we've faked being in
PLAYER_SPEED = PLAYER_SPEED - 2 ;the middle of a hyperjump. Without this FLAG, the player ship would start each game
End If ;travelling at about -90 speed backwards, which would just be weird! :)
End If
If hypercount = 100 Then
game_stars_randomize() ;half way through the Hyperjump sequence, the "game_stars_randomize()" function is called, which changes all the star positions
;and depths, to give the impression we've moved to a completely different part of space
End If
If hypercount/10 = Int(hypercount/10) Then
game_player_randomize() ;every 10 updates, the function "game_player_randomize()" is called. This randomly jumps the player around the map
;and confuses the hell out of the bad guys! (well it will by next month's tutorial!!) ;))
End If
If hypercount = 200 Then ;if the "hypercount" variable reaches 200, then stop the sequence and reset the value back to 0
hypercount = 0
FLAG_GAMESTARTER = 0 ;also, when the game first starts we were in the middle of a hyperjump. Resetting this FLAG back to 0 means that
;the next hyperjump sequence will decrease the speed after "hypercount" gets to 103
End If
Else ;if we're not in the middle of a hyperjump event, then:
frame1=game_player_frame-1 ;this bit is just for the DEBUG mode. It was designed to check that 360 degrees became 0 degrees and vice versa correctly
frame2=game_player_frame+1
If frame1 < 0 Then
frame1 = frame1 + 72
End If
If frame2 >= 72 Then
frame2 = frame2 - 72
End If
End If ;end of the "Are we in the middle of a Hyperjump" IF statement
;the parralex stars move relative to the player and is just the same "menustars" number of stars
;scrolled at various speeds, wrapping around the screen.
;it's a fairly cheap, but effective way of creating a nice illusion of speed!
If starson=1 Then ;if, at the beginning of the program, you set "starson" to 0, the stars will disappear.
;the game would also feel pretty bloody wierd.. hold on.. yep.. Absolutely mad! Try it! :)
For star.stars=Each stars
;the following two lines move each version of the "stars" Type an x and y distance relative to the player's speed and angle
;with a devision relative to the depth of the star to make the smallest stars move slower than the biggest
;thus we have our parallex effect.
;it might be of interest to know that these two lines were based on the OLDSKOOL demo which comes with Blitz Basic
;and was the starting point for the whole CELESTIAL RIFT game concept! Thanks a lot, Mr Mikkel L°kke!! :)
;the following text will only be printed on the screen while the "FLAG_DEBUG" variable is set to 1 (which for the purpose of this tutorial, we've left it at!)
If FLAG_DEBUG = 1 Then
;the TEXT command writes a STRING of text onto the screen at the given coordinates in the currently set font
;as I haven't used the LoadFont or SetFont commands, this will just be Blitz' default font.
Color 255,255,255 ;just in case, set the colo(u)r of the text to WHITE (255, 255, 255)
Text 0,0,"PLAYER ANGLE = " + PLAYER_ANGLE ;"Write the string 'PLAYER ANGLE = ' followed by the number held in PLAYER_ANGLE"
Text 0,20,"PLAYER SPEED = " + PLAYER_SPEED
Text 0,40,PLAYER_ANGLE + " / 5 = " + PLAYER_ANGLE/5
Text 0,60,"SHIPFRAME = " + game_player_frame
Text 0,80,"CO-ORDS = " + Int(PLAYER_X)
Text 140,80," , "
Text 160,80,Int(PLAYER_Y)
Text 0,120, "SCORE = " + PLAYER_SCORE
End If
;just like in "menu_draw_update()", the user can press a key which just makes the value of "FLAG_SCREENSAVE" equal 1.
;when the code gets to here, it saves out the named Buffer as a BMP picture.
If FLAG_SAVESCREEN=1 Then
SaveBuffer (BackBuffer(),"CRGameScreen.bmp")
FLAG_SAVESCREEN = 0
End If
Flip ;as before in "menu_draw_update()", FLIP everything we've just drawn on the backbuffer and show it on the frontbuffer, i.e.: your monitor!!
End Function
;a little function which randomizes the x and y coordinates of each version of the "stars" Type, plus it's "depth" property
Function game_stars_randomize()
For star.stars=Each stars
star\x=Rnd(-5,SCREEN_WIDTH) ;create random x and y positions for all the stars
star\y=Rnd(-5,SCREEN_HEIGHT)
star\depth=Rnd(1,5) ;the depth of the stars results in our sexy parallex effect
Next
End Function
;an even littler function which just gives us random x and y coordinates for the player.